package com.albaba.designpattern.beans;

import com.albaba.designpattern.beans.support.BeanDefinitionRegistry;
import com.albaba.designpattern.beans.utils.SpringUtils;
import com.albaba.designpattern.beans.xml.XmlBeanDefinitionReader;

import java.lang.reflect.Method;

/**
 * @author zx
 * @version 1.0
 * @description TODO
 * @date 2025/3/8 20:27
 */
public class ClassPathXmlApplicationContext extends AbstractApplicationContext {

    public ClassPathXmlApplicationContext(String configLocation) {
        this.configLocation = configLocation;
        // 构建解析器对象,指定具体解析类为XML
        this.beanDefinitionReader = new XmlBeanDefinitionReader();
    }

    // 根据 bean 的对象名称获取 bean 对象
    @Override
    public Object getBean(String beanName) throws Exception {

        // 判断对象容器中是否包含指定名称的 bean 对象，有则返回，没有则创建
        Object object = singletonObjects.get(beanName);
        if (object != null) {
            return object;
        }

        // 自行创建，获取 BeanDefinition 对象
        BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
        BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);

        // 通过反射创建对象
        String className = beanDefinition.getClassName();
        Class clazz = Class.forName(className);

        // 实例化
        Object beanObject = clazz.newInstance();

        // 需要进行依赖注入
        MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();

        for (PropertyValue propertyValue : propertyValues) {
            // 获取 property 标签的属性
            String propertyName = propertyValue.getName();
            String ref = propertyValue.getRef();
            String value = propertyValue.getValue();

            if (ref != null && !"".equals(ref)) {
                // 获取依赖的 bean 对象
                Object bean = getBean(ref);

                String setterMethod = SpringUtils.getSetterMethod(propertyName);

                // 获取所有的方法
                Method[] methods = clazz.getMethods();

                for (Method method : methods) {
                    if (method.getName().equalsIgnoreCase(setterMethod)) {
                        method.invoke(beanObject, bean);
                    }
                }
            }

            if (value != null && !"".equals(value)) {
                String setterMethod = SpringUtils.getSetterMethod(propertyName);
                // 获取 method
                Method method = clazz.getMethod(setterMethod, String.class);
                method.invoke(beanObject, value);
            }
        }

        // 在返回 beanObject之前，需要将对象存储在Map容器中
        this.singletonObjects.put(beanName, beanObject);
        return beanObject;
    }

    @Override
    public <T> T getBean(String name, Class<? extends T> clazz) throws Exception {

        Object bean = getBean(name);
        if (bean == null){
            return null;
        }
        return clazz.cast(bean);
    }
}
